import { toNumber, toString } from "@lib/com.verify";

/** 返回四则运算结果（从 chatgpt 复制的）
 * @expression 四则运算表达式
 * @variables 参与四则运算的变量
 */
export function doArithmeticFour(expression: string) {
  const result = _doArithmeticFour(toString(expression));
  return toNumber(result);
}

function _doArithmeticFour(expression: string): number {
  // 运算符优先级
  const precedence: { [key: string]: number } = { "+": 1, "-": 1, "*": 2, "/": 2 };
  const operators = new Set(["+", "-", "*", "/"]);

  // 将中缀表达式转换为后缀表达式
  const toPostfix = (expression: string): string[] => {
    const output: string[] = [];
    const operatorStack: string[] = [];
    const tokens = expression.match(/(\d+(\.\d+)?)|[+\-*/()]|[-+]/g);
    if (!tokens) throw new Error("无效的表达式");

    let previousToken: string | null = null;

    for (let token of tokens) {
      if (!isNaN(Number(token))) {
        output.push(token);
        previousToken = token;
      } else if (operators.has(token)) {
        if (token === "-" && (previousToken === null || operators.has(previousToken) || previousToken === "(")) {
          output.push("0");
        }
        while (
          operatorStack.length &&
          precedence[operatorStack[operatorStack.length - 1]] >= precedence[token] &&
          operatorStack[operatorStack.length - 1] !== "("
        ) {
          output.push(operatorStack.pop()!);
        }
        operatorStack.push(token);
        previousToken = token;
      } else if (token === "(") {
        operatorStack.push(token);
        previousToken = token;
      } else if (token === ")") {
        while (operatorStack.length && operatorStack[operatorStack.length - 1] !== "(") {
          output.push(operatorStack.pop()!);
        }
        if (operatorStack.length === 0) throw new Error("括号不匹配");
        operatorStack.pop(); // 弹出 '('
        previousToken = token;
      } else {
        throw new Error("无效的令牌");
      }
    }

    while (operatorStack.length) {
      const op = operatorStack.pop()!;
      if (op === "(") throw new Error("括号不匹配");
      output.push(op);
    }

    return output;
  };

  // 计算后缀表达式
  const evaluatePostfix = (postfix: string[]): number => {
    const stack: number[] = [];
    for (let token of postfix) {
      if (!isNaN(Number(token))) {
        stack.push(Number(token));
      } else {
        const b = stack.pop()!;
        const a = stack.pop()!;
        switch (token) {
          case "+":
            stack.push(a + b);
            break;
          case "-":
            stack.push(a - b);
            break;
          case "*":
            stack.push(a * b);
            break;
          case "/":
            stack.push(a / b);
            break;
        }
      }
    }
    if (stack.length !== 1) throw new Error("无效的表达式");
    return stack.pop()!;
  };

  if (!expression.trim()) throw new Error("表达式不能为空");

  return evaluatePostfix(toPostfix(expression));
}
